#include "object.hh"

Object::Object (int id, Vector3f pos, Vector3f size, int playerid):
  id_ (id),
  posid_ (0),
  playerid_ (playerid),
  speed_ (0, 0, 0),
  accel_ (0, 0, 0),
  // FIXME: Std::map of speed_coef depending on the id.
  speed_coef_ (0.3),
  direction_ (0, 0, 0)
{
  size.print();
  if (id_ == BOX)
  {
    main_bounding_ = new BoundingBox (pos, size);
    mass_ = 5;
  }
  else if (id_ == SPHERE)
  {
    main_bounding_ = new BoundingSphere (pos, size);
    mass_ = 5;
  }
  else
  {
    std::cerr << "Bad id:  " << id_ << std::endl
      << "Good values are: cube, sphere, file." << std::endl;
    // Assert is not very appropriate.
    assert (false);
  }
}

int
Object::operator() ()
{
  return id_;
}

Object::~Object ()
{
}

void
Object::speed_add (Vector3f speed)
{
  speed_ += speed;
}

void
Object::accel_add (Vector3f accel)
{
  accel_ += accel;
}

void
Object::pos_set (const Vector3f& pos)
{
  main_bounding_->pos (pos);
}

void
Object::move (const Vector3f& pos)
{
  Vector3f new_pos = main_bounding_->pos ();
  new_pos += pos;
  main_bounding_->pos (new_pos);
}

const Vector3f&
Object::pos_get () const
{
  return main_bounding_->pos ();
}

void
Object::speed_set (Vector3f speed)
{
  speed_ = speed;
}
Vector3f
Object::speed_get ()
{
  return speed_;
}

void
Object::accel (Vector3f accel)
{
  accel_ = accel;
}

Vector3f
Object::accel ()
{
  return accel_;
}

void
Object::receive_message (int msg)
{
  if (msg == MOVE_LEFT)
    speed_add (Vector3f (-0.001, 0, 0));
  else if (msg == MOVE_RIGHT)
    speed_add (Vector3f (0.001, 0, 0));
  else if (msg == MOVE_UP)
    speed_add (Vector3f (0, -0.001, 0));
  else if (msg == MOVE_DOWN)
    speed_add (Vector3f (0, 0.001, 0, 0));
}

Bounding* Object::main_bounding_get ()
{
  return main_bounding_;
}

bool Object::intersect (Object* obj)
{
  return main_bounding_->intersect (obj->main_bounding_get ());
}
bool Object::intersectWall(Plane& p)
{
  return main_bounding_->intersectWall (p);
}

std::string
Object::tonet () const
{
  std::string res;

  char* posid = (char*) &posid_;
  for (int i = 0; i < 4; ++i)
    res += posid[i];

  char* id = (char*) &id_;
  for (int i = 0; i < 4; ++i)
    res += id[i];

  unsigned char c;
  assert (main_bounding_->size () (0) < 127);
  c = (unsigned char) main_bounding_->size () (0);

  if (dynamic_cast<const BoundingSphere*> (main_bounding_))
    res += c;
  else
    assert (false);    //no other type for now

  res += main_bounding_->rotate ().tonet ();
  res += main_bounding_->pos ().tonet ();

  return res;
}

std::string
Object::tonetupdate () const
{
  std::string res;

  char* posid = (char*) &posid_;
  for (int i = 0; i < 4; ++i)
    res += posid[i];

  res += main_bounding_->rotate ().tonet ();
  res += main_bounding_->pos ().tonet ();

  return res;
}

const Vector3f&
Object::size_get () const
{
  return main_bounding_->size ();
}

int
Object::id_get ()
{
  return id_;
}

int Object::posid () const
{
  return posid_;
}

void Object::posid (int id)
{
  posid_ = id;
}

void
Object::rotate (const Vector3d& rot)
{
  Vector3d rotate = main_bounding_->rotate ();

  rotate (0, (rotate (0) + rot (0)) % 360);
  rotate (1, (rotate (1) + rot (1)) % 360);
  rotate (2, (rotate (2) + rot (2)) % 360);

  main_bounding_->rotate (rotate);
}

const Vector3d&
Object::rotate () const
{
  return main_bounding_->rotate ();
}

Vector3f
Object::direction ()
{
  return direction_;
}

void
Object::direction (Vector3f direction)
{
  direction_ = direction;
}

float Object::speed_coef ()
{
  return speed_coef_;
}

void Object::speed_coef (float coef)
{
  speed_coef_ = coef;
}

void Object::new_direction (Vector3f direction)
{
  direction_ = direction;
  speed_ = direction_ * speed_coef_;
}

void Object::mass (float m)
{
  mass_ = m;
}

float Object::mass ()
{
  return mass_;
}
